/*Main*/ 
#include "stdafx.h"
#include "Globals.h"
#include "Test.h"
#include "SenseBarrier.h"

IBarrier *g_bar = new SenseBarrier(Globals::numberOfThreads);

using namespace std;

#define WITHWAIT

/*
 * Impl of the pure virtual function.  
 */	
void SenseBarrier::await() {
	int mySense = threadLocal.get();
	int pos = _count.getAndDecrement();

	if (pos == 1)
	{
		_count.set(_size);
		_sense = mySense; // release threads.
		MB();
	} else
	{
		while (_sense != mySense)
		{
#ifdef WITHWAIT
			Thread::yield();
#endif
		} 
	}

	int myNewSense = (mySense + 1) % 2;
	threadLocal.set(myNewSense); // toggle sense
}

// MAIN
// first arg	= number of threads
// second arg	= max count to 
// third arg	= number of iterations 
// forth arg	= test type 0=counter, 1=localCounter 2=matrix
// fifth arg	= shared memory - 1 for shared mem, 0 for local mem.
// sixth arg	= barrier type. 0=SenseWithWait, 1=LinearSense, 2=BinaryStaticBarrier
int main(int argc,char* argv[])
{
	TestFactory factory;
	TestType testType = Matrix; // default test type
	if (argc > 1)
	{
		Globals::numberOfThreads = atoi(argv[1]);
	}
	
	if (argc > 2)
	{
		Globals::countTo = atoi(argv[2]);
	}

	if (argc > 3)
	{
		Globals::numberOfIterations = atoi(argv[3]);
	}

	if (argc > 4)
	{
		int typeId = atoi(argv[4]);
		if (typeId == 0)
		{
			testType = Counter;
		} else if (typeId == 1)
		{
			testType = LocalCounter;
		} else if (typeId == 2)
		{
			testType = Matrix;
		} else {
			printf("Unsupported TestType id: %d. Exiting.\n", typeId);
			assert(false);
		}
	}

	
	g_bar = new SenseBarrier(Globals::numberOfThreads);
	printf("%s, Number of threads, %d, count to, %d, numOfIters:,%d\n", g_bar->getBarrierName(), Globals::numberOfThreads, Globals::countTo, Globals::numberOfIterations);
	fflush(stdout);

	Test* test = factory.createTest(g_bar, testType);
	
	test->performTest();
}

